package com.example.xunai.service.ai.strategy.impl;

import com.example.xunai.config.AiModelConfig;
import com.example.xunai.service.ai.strategy.AiModelStrategy;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
@RequiredArgsConstructor
public class QwenStrategy implements AiModelStrategy {

    private final ObjectMapper objectMapper;
    private final RestTemplate restTemplate = new RestTemplate();

    @Override
    public String getModelType() {
        return "qwen";
    }

    @Override
    public String chatSync(String message, List<Map<String, String>> conversationContext, AiModelConfig.ModelConfig config) {
        try {
            Map<String, Object> requestBody = buildRequestBody(conversationContext, config, false);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + config.getApiKey());

            log.info("发送通义千问请求，URL: {}, 模型: {}", config.getApiUrl(), config.getModelName());

            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

            ResponseEntity<Map> response = restTemplate.exchange(
                    config.getApiUrl(),
                    HttpMethod.POST,
                    request,
                    Map.class
            );

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                String result = parseSyncResponse(response.getBody());
                log.info("通义千问响应成功，内容长度: {}", result != null ? result.length() : 0);
                return result;
            }

            log.error("通义千问API请求失败: {}", response.getStatusCode());
            return "API请求失败: " + response.getStatusCode();

        } catch (Exception e) {
            log.error("通义千问同步请求失败", e);
            return "请求出错: " + e.getMessage();
        }
    }

    @Override
    public SseEmitter chatStream(String message, List<Map<String, String>> conversationContext,
                                 AiModelConfig.ModelConfig config, StreamCallback callback) {
        SseEmitter emitter = new SseEmitter(120_000L);
        StringBuilder fullResponse = new StringBuilder();

        new Thread(() -> {
            try {
                URL url = new URL(config.getApiUrl());
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("Authorization", "Bearer " + config.getApiKey());
                connection.setRequestProperty("Accept", "text/event-stream");
                connection.setRequestProperty("Cache-Control", "no-cache");
                connection.setDoOutput(true);
                connection.setReadTimeout(120000);

                Map<String, Object> requestBody = buildRequestBody(conversationContext, config, true);
                String jsonInput = objectMapper.writeValueAsString(requestBody);

                log.info("发送通义千问流式请求，URL: {}, 模型: {}", config.getApiUrl(), config.getModelName());

                try (var outputStream = connection.getOutputStream()) {
                    outputStream.write(jsonInput.getBytes(StandardCharsets.UTF_8));
                    outputStream.flush();
                }

                int responseCode = connection.getResponseCode();
                if (responseCode != HttpStatus.OK.value()) {
                    String errorResponse = readErrorResponse(connection);
                    log.error("通义千问API错误: {} - {}", responseCode, errorResponse);
                    callback.onError("API请求失败: " + responseCode + " - " + errorResponse);
                    emitter.complete();
                    return;
                }

                // 处理流式响应
                try (var reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (line.trim().isEmpty()) continue;

                        if (line.startsWith("data: ")) {
                            String data = line.substring(6).trim();

                            if ("[DONE]".equals(data)) {
                                log.info("通义千问流式传输完成");
                                callback.onComplete();
                                break;
                            }

                            try {
                                Map<String, Object> eventData = objectMapper.readValue(data, Map.class);
                                String content = extractContentFromEvent(eventData);

                                if (content != null && !content.isEmpty()) {
                                    fullResponse.append(content);
                                    callback.onContent(content);
                                }
                            } catch (Exception e) {
                                log.warn("解析流式JSON失败: {} - {}", data, e.getMessage());
                            }
                        }
                    }
                    emitter.complete();
                }

            } catch (Exception e) {
                log.error("通义千问流式请求异常", e);
                callback.onError("请求处理失败: " + e.getMessage());
                emitter.complete();
            }
        }).start();

        return emitter;
    }

    @Override
    public boolean validateConfig(AiModelConfig.ModelConfig config) {
        return config.getApiKey() != null && !config.getApiKey().trim().isEmpty() &&
                config.getApiUrl() != null && !config.getApiUrl().trim().isEmpty() &&
                config.getModelName() != null && !config.getModelName().trim().isEmpty();
    }

    /**
     * 构建通义千问请求体（OpenAI兼容格式）:cite[4]:cite[8]
     */
    private Map<String, Object> buildRequestBody(List<Map<String, String>> messages,
                                                 AiModelConfig.ModelConfig config, boolean stream) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", config.getModelName());
        requestBody.put("messages", messages);
        requestBody.put("stream", stream);

        if (config.getTemperature() != null) {
            requestBody.put("temperature", config.getTemperature());
        }
        if (config.getMaxTokens() != null) {
            requestBody.put("max_tokens", config.getMaxTokens());
        }

        return requestBody;
    }

    /**
     * 解析通义千问响应（OpenAI兼容格式）:cite[4]
     */
    private String parseSyncResponse(Map<String, Object> body) {
        try {
            log.debug("通义千问完整响应: {}", body);

            // OpenAI兼容的响应格式
            if (body.containsKey("choices")) {
                List<?> choices = (List<?>) body.get("choices");
                if (!choices.isEmpty() && choices.get(0) instanceof Map) {
                    Map<?, ?> choice = (Map<?, ?>) choices.get(0);
                    if (choice.containsKey("message") && choice.get("message") instanceof Map) {
                        Map<?, ?> message = (Map<?, ?>) choice.get("message");
                        if (message.containsKey("content") && message.get("content") instanceof String) {
                            return (String) message.get("content");
                        }
                    }
                }
            }

            // 错误响应
            if (body.containsKey("error")) {
                Map<?, ?> error = (Map<?, ?>) body.get("error");
                String errorMsg = error.containsKey("message") ? (String) error.get("message") : "未知错误";
                log.error("通义千问API返回错误: {}", errorMsg);
                return "API错误: " + errorMsg;
            }

            log.warn("通义千问响应格式异常: {}", body);
            return "响应格式异常";

        } catch (Exception e) {
            log.error("解析通义千问响应失败", e);
            return "解析响应失败: " + e.getMessage();
        }
    }

    /**
     * 从事件数据中提取内容（流式响应解析）
     */
    private String extractContentFromEvent(Map<String, Object> eventData) {
        try {
            log.debug("解析通义千问流式事件数据: {}", eventData);

            // OpenAI兼容的流式格式
            if (eventData.containsKey("choices")) {
                List<?> choices = (List<?>) eventData.get("choices");
                if (!choices.isEmpty() && choices.get(0) instanceof Map) {
                    Map<?, ?> choice = (Map<?, ?>) choices.get(0);
                    if (choice.containsKey("delta") && choice.get("delta") instanceof Map) {
                        Map<?, ?> delta = (Map<?, ?>) choice.get("delta");
                        if (delta.containsKey("content") && delta.get("content") instanceof String) {
                            String content = (String) delta.get("content");
                            log.debug("提取到流式内容: {}", content);
                            return content;
                        }
                    }
                }
            }

            return null;
        } catch (Exception e) {
            log.warn("解析流式响应内容失败", e);
            return null;
        }
    }

    /**
     * 读取错误响应
     */
    private String readErrorResponse(HttpURLConnection connection) {
        try {
            if (connection.getErrorStream() != null) {
                try (var errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
                    StringBuilder errorResponse = new StringBuilder();
                    String line;
                    while ((line = errorReader.readLine()) != null) {
                        errorResponse.append(line);
                    }
                    return errorResponse.toString();
                }
            }
            return "无错误信息";
        } catch (Exception e) {
            return "无法读取错误信息: " + e.getMessage();
        }
    }
}